package com.banca2.bracketplant.communicate;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.banca2.bracketplant.common.RequestType;
import com.banca2.bracketplant.common.ResponseStatus;
import com.banca2.bracketplant.pojo.BncResponse;

/*********************************************************************<br>
 * HttpHelper.java													 *<br>
 * 功 能：				 												 *<br>
 * 	封装HTTP请求相关接口												 *<br>
 * 																	 *<br>
 *  Ver   变更日期        负责人  					变更内容                        			 *<br>
 * ───────────────────────────────────────────────────────────────── *<br>
 * V0.01 2015-6-1	ZQ      				    创建					 *<br>
 * 																	 *<br>
 * Copyright (c) 2015 StarFollower Corporation. All rights reserved. *<br>
 *┌─────────────────────────────────────────────────────────────────┐*<br>
 *│　此技术信息为本团队机密信息，未经本团队书面同意禁止向第三方披露．　				│*<br>
 *│　版权所有：StarFollower　　　　　　　　　　                     　					│*<br>
 *└─────────────────────────────────────────────────────────────────┘*<br>
 *********************************************************************/
public class HttpHelper {

	private static final String LOG_TAG = HttpHelper.class.getSimpleName();

	// 服务器URL头，不包含“文件名”部分
	private static final String SERVER_ADDRESS = "xxx/";

	// 请求参数的标准键名
	private static final String KEY_PARAMS = "params";

	// 部分HTTP请求参数
	private static int HTTP_CONNECTION_TIMEOUT = 60000;
	private static int HTTP_SOCKET_TIMEOUT = 60000;
	private static String HTTP_CHARSET = "UTF-8";

	private static HttpClient httpClient = new DefaultHttpClient();

	/**
	 * 执行一次服务器请求
	 * 
	 * @param isPost
	 *            HTTP方法类型
	 * @param requestType
	 *            请求类型，即URL的“文件名”部分
	 * @param params
	 *            请求参数
	 * @return BncResponse
	 * 
	 * @author ZQ(上午8:57:18)
	 */
	static BncResponse doRequest(boolean isPost, RequestType requestType, Object params) {
		BncResponse result = null;
		try {
			Log.v(LOG_TAG, "doRequest(boolean, RequestType,Object, ResponseProcessor) - start");

			// 配置HTTP方法
			HttpUriRequest uriRequest = null;
			if (isPost) {
				uriRequest = createPostRequest(requestType, params);
			} else {
				uriRequest = createGetRequest(requestType, params);
			}

			// 执行网络访问
			Log.i(LOG_TAG, "即将开始网络访问");
			long startTime = System.currentTimeMillis();
			HttpResponse httpResponse = httpClient.execute(uriRequest);
			Log.i(LOG_TAG, "网络访问结束，耗时"
					+ ((System.currentTimeMillis() - startTime) / 1000f) + "秒");

			// 解析HttpResponse
			if (httpResponse != null) {
				int netStatusCode = httpResponse.getStatusLine()
						.getStatusCode();
				if (200 == netStatusCode) {
					HttpEntity entity = httpResponse.getEntity();
					if (entity != null) {
						// 网络访问成功
						String strResult = EntityUtils.toString(entity, HTTP_CHARSET);
						Log.i(LOG_TAG, "网络访问成功：" + strResult);

						result = JSON.parseObject(strResult, BncResponse.class);
					} else {
						// 网络访问失败
						Log.e(LOG_TAG, "HttpResponse.getEntity()=null");
						result = new BncResponse(ResponseStatus.SERVER_ERROR);
					}// if entity
				} else {
					// 网络访问失败
					Log.e(LOG_TAG, "netStatusCode=" + netStatusCode);
					result = new BncResponse(ResponseStatus.COMMUNICATION_ERROR);
				}// if netStatusCode
			} else {
				// 网络访问失败
				Log.e(LOG_TAG, "HttpResponse=null");
				result = new BncResponse(ResponseStatus.COMMUNICATION_ERROR);
			}// if HttpResponse

		} catch (HttpMethodCreatorException e) {
			Log.e(LOG_TAG, "封装Http方法异常", e);
			result = new BncResponse(ResponseStatus.CLIENT_ERROR);
		} catch (ClientProtocolException e) {
			Log.e(LOG_TAG, "网络通讯异常", e);
			result = new BncResponse(ResponseStatus.COMMUNICATION_ERROR);
		} catch (IOException e) {
			Log.e(LOG_TAG, "网络通讯异常", e);
			result = new BncResponse(ResponseStatus.COMMUNICATION_ERROR);
		} catch (Exception e) {
			Log.e(LOG_TAG, "未知异常", e);
			result = new BncResponse(ResponseStatus.CLIENT_ERROR);
		}
		
		Log.v(LOG_TAG, "doRequest(boolean, RequestType,Object, ResponseProcessor) - end");
		return result;
	}// doRequest

	/**
	 * 封装HttpPost
	 * 
	 * @param requestType
	 *            请求类型，即URL的“文件名”部分
	 * @param params
	 *            请求参数
	 * @return HttpPost
	 * @throws HttpMethodCreatorException
	 *             通讯出现异常
	 * 
	 * @author ZQ(上午8:27:23)
	 */
	private static HttpPost createPostRequest(RequestType requestType,
			Object params) throws HttpMethodCreatorException {
		try {
			Log.v(LOG_TAG, "createPostRequest(RequestType, JSONObject) - start");

			// 配置HTTP参数
			HttpPost httpPost = new HttpPost();
			httpPost.addHeader("Content-Type", "text/json");
			httpPost.addHeader("charset", HTTP_CHARSET);
			httpPost.addHeader("Cache-Control", "no-cache");

			HttpParams httpParameters = httpPost.getParams();
			HttpConnectionParams.setConnectionTimeout(httpParameters, HTTP_CONNECTION_TIMEOUT);
			HttpConnectionParams.setSoTimeout(httpParameters, HTTP_SOCKET_TIMEOUT);
			httpPost.setParams(httpParameters);

			httpPost.setURI(new URI(SERVER_ADDRESS + requestType));
			Log.i(LOG_TAG, "HttpPost准备：URI=" + SERVER_ADDRESS + requestType);
			if (null != params) {
				// 准备请求参数
				// {params=【真正的参数】}价值：
				// 1、使得GET方法请求参数从URI故由模式中剥离出来，便于客户端封装统一的GET方法
				// 2、屏蔽了参数类型为JSONObject或JSONArray的区别，便于服务器统一提取参数
				JSONObject jsonParams = new JSONObject();
				jsonParams.put(KEY_PARAMS, params);
				httpPost.setEntity(new StringEntity(jsonParams.toString(),
						HTTP.UTF_8));
				Log.i(LOG_TAG, "HttpPost准备：params=" + jsonParams.toString());
			}

			Log.v(LOG_TAG, "createPostRequest(RequestType, JSONObject) - end");
			return httpPost;
		} catch (URISyntaxException e) {
			// URI包含特殊字符
			Log.e(LOG_TAG, "createPostRequest(RequestType, JSONObject) - ERROR");
			throw new HttpMethodCreatorException(e);
		} catch (UnsupportedEncodingException e) {
			// StringEntity编码异常，此种情况不应该发生，发生则为不可恢复的运行时异常
			Log.e(LOG_TAG, "createPostRequest(RequestType, JSONObject) - ERROR");
			throw new HttpMethodCreatorException(e);
		} catch (Exception e) {
			Log.e(LOG_TAG, "createPostRequest(RequestType, JSONObject) - ERROR");
			throw new HttpMethodCreatorException("未知异常", e);
		}
	}// end createPostRequest

	/**
	 * 封装HttpGet
	 * 
	 * @param requestType
	 *            请求类型，即URL的“文件名”部分
	 * @param params
	 *            请求参数
	 * @return HttpGet
	 * @throws HttpMethodCreatorException
	 *             通讯出现异常
	 * 
	 * @author ZQ(上午8:27:23)
	 */
	private static HttpGet createGetRequest(RequestType requestType,
			Object params) throws HttpMethodCreatorException {
		try {
			Log.v(LOG_TAG, "createGetRequest(RequestType, JSONObject) - start");

			// 准备请求参数
			// {params=【真正的参数】}价值：
			// 1、使得GET方法请求参数从URI故由模式中剥离出来，便于客户端封装统一的GET方法
			// 2、屏蔽了参数类型为JSONObject或JSONArray的区别，便于服务器统一提取参数
			String url = SERVER_ADDRESS
					+ requestType
					+ "?_="
					+ System.currentTimeMillis()
					+ (null == params ? "" : "&" + KEY_PARAMS + "="
							+ JSON.toJSONString(params));
			Log.i(LOG_TAG, "URL=" + url);
			url = URLEncoder.encode(url, HTTP_CHARSET);
			Log.d(LOG_TAG, HTTP_CHARSET + "编码后URL=" + url);

			// 配置HTTP参数
			HttpGet httpGet = new HttpGet(url);
			httpGet.addHeader("Content-Type", "text/json");
			httpGet.addHeader("charset", "UTF-8");
			httpGet.addHeader("Cache-Control", "no-cache");

			HttpParams httpParameters = httpGet.getParams();
			HttpConnectionParams.setConnectionTimeout(httpParameters, HTTP_CONNECTION_TIMEOUT);
			HttpConnectionParams.setSoTimeout(httpParameters, HTTP_SOCKET_TIMEOUT);
			httpGet.setParams(httpParameters);

			Log.v(LOG_TAG, "createGetRequest(RequestType, JSONObject) - end");
			return httpGet;
		} catch (UnsupportedEncodingException e) {
			Log.e(LOG_TAG, "createGetRequest(RequestType, JSONObject) - ERROR");
			throw new HttpMethodCreatorException(e);
		} catch (Exception e) {
			Log.e(LOG_TAG, "createGetRequest(RequestType, JSONObject) - ERROR");
			throw new HttpMethodCreatorException("未知异常",e);
		}
	}// end createGetRequest

	// /**
	// * 显示“正在载入”用户界面
	// *
	// * @author ZQ(上午1:16:53)
	// */
	// private static void showLoading(ResponseProcessor processor){
	// if(null != processor && ! processor.isLoading()){
	// processor.showLoading();
	// }
	// }//showLoading
	//
	// /**
	// * 隐藏“正在载入”用户界面
	// *
	// * @author ZQ(上午1:17:51)
	// */
	// private static void hideLodding(ResponseProcessor processor){
	// if(null != processor && processor.isLoading()){
	// processor.hideLodding();
	// }
	// }//hideLodding
	//
	// /**
	// * 显示异常信息
	// * @param errorMsg
	// *
	// * @author ZQ(上午1:30:47)
	// */
	// private static void showErrorMsg(int errorMsg, ResponseProcessor
	// processor){
	// if(null != processor){
	// processor.hideLodding();
	// processor.showErrorMsg(errorMsg);
	// }
	// }//showErrorMsg
	//
	// /**
	// * 处理服务器返回的响应数据
	// * @param jsonData
	// *
	// * @author ZQ(上午1:30:18)
	// */
	// private static void processData(JSONObject jsonData, ResponseProcessor
	// processor){
	// if(null != processor){
	// processor.hideLodding();
	// processor.processData(jsonData);
	// }
	// }//processData

}
